﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EasyNet.Componets.Core;
using System.Reflection;

namespace EasyNet.Componets.Cache.Redis.StackExchange
{
    /// <summary>
    /// 用于Redis的缓存项，缓存对象类型的类型，当获取缓存的时候可以取会对应的类型
    /// </summary>
    internal class CacheItem
    {
        private static IDictionary<string, Type> TypeDictionary = new Dictionary<string, Type>();

        private static readonly Object _locker = new object();

        public CacheItem(object obj)
        {
            this.CachedObjectType = obj.GetType().FullName;
            this.CachedObjectTypeBeloneAssembly = obj.GetType().Assembly.GetName().Name;
            this.CachedObjectJsonString = obj.ToJsonString();
        }

        /// <summary>
        /// 被缓存的对象的类型
        /// </summary>
        public string CachedObjectType { get; private set; }

        /// <summary>
        /// 被缓存的对象的类型所属程序集
        /// </summary>
        public string CachedObjectTypeBeloneAssembly { get; private set; }

        /// <summary>
        /// 被缓存的对象的JSON格式
        /// </summary>
        public string CachedObjectJsonString { get; private set; }

        /// <summary>
        /// 获取缓存的对象
        /// </summary>
        public object GetCachedObject()
        {
            var type = GetTypeInfo();

            return Core.Utils.SerializationUtil.Json.Deserialize(CachedObjectJsonString, type);
        }

        /// <summary>
        /// 获取Type类型
        /// </summary>
        private Type GetTypeInfo()
        {
            Type type = null;

            if (!TypeDictionary.ContainsKey(this.CachedObjectType))
            {
                lock (_locker)
                {
                    //二次验证
                    if (!TypeDictionary.ContainsKey(this.CachedObjectType))
                    {
                        //获取对象的类型信息
                        var assembly = Assembly.Load(this.CachedObjectTypeBeloneAssembly);
                        type = assembly.GetType(this.CachedObjectType);
                        TypeDictionary.Add(this.CachedObjectType, type);
                    }
                    else
                    {
                        type = TypeDictionary[this.CachedObjectType];
                    }
                }
            }
            else
            {
                type = TypeDictionary[this.CachedObjectType];
            }

            return type;
        }
    }
}
